/*
 * COPYRIGHT. ShenZhen JiMi Technology Co., Ltd. 2017.
 * ALL RIGHTS RESERVED.
 *
 * No part of this publication may be reproduced, stored in a retrieval system, or transmitted,
 * on any form or by any means, electronic, mechanical, photocopying, recording, 
 * or otherwise, without the prior written permission of ShenZhen JiMi Network Technology Co., Ltd.
 *
 * Amendment History:
 * 
 * Date                   By              Description
 * -------------------    -----------     -------------------------------------------
 * 2017年4月12日    li.shangzhi         Create the class
 * http://www.jimilab.com/
 */

package com.jimi.api.devices.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sf.oval.constraint.DateRange;
import net.sf.oval.constraint.Length;
import net.sf.oval.constraint.Max;
import net.sf.oval.constraint.MemberOf;
import net.sf.oval.constraint.Min;
import net.sf.oval.constraint.NotBlank;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.jimi.api.devices.DevicesApi;
import com.jimi.api.devices.vo.GpsPointVo;
import com.jimi.api.user.vo.DeviceLocationInfoVo;
import com.jimi.dto.base.ApiResult;
import com.jimi.exception.ApiErrorCode;
import com.jimi.exception.ErrorCode;
import com.jimi.framework.base.BaseController;
import com.jimi.framework.bean.BeanUtil;
import com.jimi.framework.interceptor.loginsecurity.LoginSecurity;
import com.jimi.framework.utils.DESEncrypt;
import com.jimi.framework.utils.DateUtil;
import com.jimi.framework.utils.FreeMarkerUtil;
import com.jimi.framework.utils.ResultModel;
import com.jimi.utils.MessageSourceUtil;
import com.jimi.web.api.IDevicesApiService;
import com.jimi.web.api.IUserApiService;
import com.jimi.web.dto.input.ElectricFenceInputDto;
import com.jimi.web.dto.output.CoreUserOutputDto;
import com.jimi.web.dto.output.DeviceInfoOutputDto;
import com.jimi.web.dto.output.DeviceLocationInfoOutputDto;
import com.jimi.web.dto.output.GpsPointOutputDto;

/**
 * @FileName DevicesApiController.java
 * @Description:
 *
 * @Date 2017年4月12日 下午1:47:39
 * @author li.shangzhi
 * @version 1.0
 */
@RestController
@RequestMapping(value = "/devices")
public class DevicesApiController extends BaseController implements DevicesApi {

	@Autowired
	private IDevicesApiService devicesApiService;
	
	@Autowired
	private IUserApiService userApiService;
	
	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/getLocations", params = { "method=jimi.device.location.get" }, produces = { "application/json" }, method = {
			RequestMethod.GET, RequestMethod.POST })
	@Override
	public ResponseEntity<ResultModel> getLocations(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @RequestParam(value = "imeis", required = true) String imeis,
			@RequestParam(value = "map_type", defaultValue = "", required = false) String mapType, HttpServletRequest request) {
		if(StringUtils.isNotBlank(mapType) && (!"BAIDU".equals(mapType) && !"GOOGLE".equals(mapType))) {
			return new ResponseEntity<ResultModel>(new ResultModel(ApiErrorCode.PARAM_MAPTYPE_ERROR), HttpStatus.OK);
		}
		String[] imeisArray = imeis.split(",");
		if (imeisArray.length > 100) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.PARAM_ERROR), HttpStatus.OK);
		}
		List<DeviceLocationInfoOutputDto> deviceLocationInfo = devicesApiService.getLocations(imeis, mapType);
		List<DeviceLocationInfoVo> resultList = (List<DeviceLocationInfoVo>) BeanUtil.convertBeanList(deviceLocationInfo,
				DeviceLocationInfoVo.class);
		ResultModel resultModel = new ResultModel();
		resultModel.setResult(resultList);
		return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
	}

	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/getTracks", params = { "method=jimi.device.track.list" }, produces = { "application/json" }, method = { RequestMethod.GET,
			RequestMethod.POST })
	@Override
	public ResponseEntity<ResultModel> getTracks(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @Length(min = 15, max = 16, message = "api.imei.invalid") @RequestParam(value = "imei", required = true) String imei,
			@NotBlank(message = "api.beginTime.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.beginTime.invalid") @RequestParam(value = "begin_time", required = true) String beginTime,
			@NotBlank(message = "api.endTime.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.endTime.invalid") @RequestParam(value = "end_time", required = true) String endTime,
			@RequestParam(value = "map_type",  defaultValue = "", required = false) String mapType, HttpServletRequest request) {
		if(StringUtils.isNotBlank(mapType) && (!"BAIDU".equals(mapType) && !"GOOGLE".equals(mapType))) {
			return new ResponseEntity<ResultModel>(new ResultModel(ApiErrorCode.PARAM_MAPTYPE_ERROR), HttpStatus.OK);
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			Date begin = dateFormat.parse(beginTime);
			Date end = dateFormat.parse(endTime);
			if(begin.after(end)) {
				return new ResponseEntity<ResultModel>(new ResultModel(ApiErrorCode.PARAM_BEGIN_DATE_ERROR), HttpStatus.OK);
			}
			if(DateUtil.getIntervalDays(begin) > 90 || DateUtil.getIntervalDays(end) > 90 || DateUtil.getIntervalDays(begin, end) > 2) {
				return new ResponseEntity<ResultModel>(new ResultModel(ApiErrorCode.PARAM_DATE_INTERVAL_ERROR), HttpStatus.OK);
			}
			
			String decrypt = DESEncrypt.decrypt(appKey);
			String[] strs = decrypt.split(",");
			String projectCode = strs[0];
			String userId = strs[1];
			DeviceInfoOutputDto deviceInfoOutputDto = devicesApiService.checkDeviceRange(userId, imei);
			if(null == deviceInfoOutputDto) {
				return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_DEVICE_ERROR), HttpStatus.OK);
			}
			
			List<GpsPointOutputDto> gpsPointList = devicesApiService.getTracks(imei, beginTime, endTime, mapType);
			List<GpsPointVo> gpsVoList = (List<GpsPointVo>) BeanUtil.convertBeanList(gpsPointList, GpsPointVo.class);
			ResultModel resultModel = new ResultModel();
			resultModel.setResult(gpsVoList);
			return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
		} catch (ParseException e) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.PARAM_ERROR), HttpStatus.OK);
		}
	}
	
	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/bindUser", params = { "method=jimi.open.device.bind" }, produces = { "application/json" }, method = { RequestMethod.POST, RequestMethod.PUT })
	@Override
	public ResponseEntity<ResultModel> bindUser(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @Length(min = 15, max = 16, message = "api.imei.invalid") @RequestParam(value = "imei", required = true) String imei,
			@NotBlank(message = "api.userId.invalid") @Length(min = 3, max = 32, message = "api.userId.invalid") @RequestParam(value = "user_id", required = true) String target,
			HttpServletRequest request) {
		String decrypt = DESEncrypt.decrypt(appKey);
		String[] strs = decrypt.split(",");
		String projectCode = strs[0];
		String userId = strs[1];
		CoreUserOutputDto coreUserOutputDto = userApiService.getAccount(target);
		if(null == coreUserOutputDto || coreUserOutputDto.getType() != 3) { // 3是终端用户
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_USER_ERROR), HttpStatus.OK);
		}
		
		DeviceInfoOutputDto deviceInfoOutputDto = devicesApiService.checkDeviceRange(userId, imei);
		if(null == deviceInfoOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_DEVICE_ERROR), HttpStatus.OK);
		}
		if(StringUtils.isNotBlank(deviceInfoOutputDto.getBindUserId())) {
			return new ResponseEntity<ResultModel>(new ResultModel(10, "该设备已绑定用户。"), HttpStatus.OK);
		}
		boolean flag = devicesApiService.bindUser(imei, String.valueOf(coreUserOutputDto.getId()), coreUserOutputDto.getAccount());
		ResultModel resultModel = new ResultModel();
		resultModel.setMessage("绑定用户" + (flag ? "成功" : "失败"));
		return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
	}
	
	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/unBindUser", params = { "method=jimi.open.device.unbind" }, produces = { "application/json" }, method = { RequestMethod.POST, RequestMethod.PUT })
	@Override
	public ResponseEntity<ResultModel> unBindUser(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @Length(min = 15, max = 16, message = "api.imei.invalid") @RequestParam(value = "imei", required = true) String imei,
			@NotBlank(message = "api.userId.invalid") @Length(min = 3, max = 32, message = "api.userId.invalid") @RequestParam(value = "user_id", required = true) String target,
			HttpServletRequest request) {
		String decrypt = DESEncrypt.decrypt(appKey);
		String[] strs = decrypt.split(",");
		String projectCode = strs[0];
		String userId = strs[1];
		CoreUserOutputDto coreUserOutputDto = userApiService.getAccount(target);
		if(null == coreUserOutputDto || coreUserOutputDto.getType() != 3) { // 3是终端用户
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_USER_ERROR), HttpStatus.OK);
		}
		
		DeviceInfoOutputDto deviceInfoOutputDto = devicesApiService.checkDeviceRange(userId, imei);
		if(null == deviceInfoOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_DEVICE_ERROR), HttpStatus.OK);
		}
		if(!String.valueOf(coreUserOutputDto.getId()).equals(deviceInfoOutputDto.getBindUserId())) {
			return new ResponseEntity<ResultModel>(new ResultModel(10, "该设备没有绑定该用户，解绑失败。"), HttpStatus.OK);
		}
		try {
			boolean flag = devicesApiService.unBindUser(imei, String.valueOf(coreUserOutputDto.getId()));
			ResultModel resultModel = new ResultModel();
			resultModel.setMessage("解除绑定" + (flag ? "成功" : "失败"));
			return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
		} catch(Exception e) {
			return new ResponseEntity<ResultModel>(new ResultModel(10, "该设备已绑定用户。"), HttpStatus.OK);
		}
	}

	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/updateDeviceInfo", params = { "method=jimi.open.device.update" }, produces = { "application/json" }, method = { RequestMethod.POST, RequestMethod.PUT })
	@Override
	public ResponseEntity<ResultModel> updateDeviceInfo(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @Length(min = 15, max = 16, message = "api.imei.invalid") @RequestParam(value = "imei", required = true) String imei,
			@Length(max = 30, message = "api.deviceName.maxLength") @RequestParam(value = "device_name", required = false) String deviceName,
			@Length(max = 30, message = "api.vehicleName.maxLength") @RequestParam(value = "vehicle_name", required = false) String vehicleName,
			@Length(max = 30, message = "api.vehicleIcon.maxLength") @RequestParam(value = "vehicle_icon", required = false) String vehicleIcon,
			@Length(max = 30, message = "api.vehicleNumber.maxLength") @RequestParam(value = "vehicle_number", required = false) String vehicleNumber,
			@Length(max = 30, message = "api.vehicleModels.maxLength") @RequestParam(value = "vehicle_models", required = false) String vehicleModels,
			@Length(max = 30, message = "api.driverName.maxLength") @RequestParam(value = "driver_name", required = false) String driverName,
			@Length(max = 30, message = "api.driverPhone.maxLength") @RequestParam(value = "driver_phone", required = false) String driverPhone,
			HttpServletRequest request) {
		String decrypt = DESEncrypt.decrypt(appKey);
		String[] strs = decrypt.split(",");
		String projectCode = strs[0];
		String userId = strs[1];
		DeviceInfoOutputDto deviceInfoOutputDto = devicesApiService.checkDeviceRange(userId, imei);
		if(null == deviceInfoOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_DEVICE_ERROR), HttpStatus.OK);
		}
		String code = devicesApiService.updateDeviceInfo(imei, deviceName, vehicleName, vehicleIcon, vehicleNumber, vehicleModels, driverName, driverPhone);
		ResultModel resultModel = new ResultModel();
		if ("0".equals(code)) {
			resultModel.setCode(0);
			resultModel.setMessage(MessageSourceUtil.getMessage("api.device.update.ok"));
		} else {
			resultModel.setCode(12006); // 更新设备信息
			resultModel.setMessage(MessageSourceUtil.getMessage("api.device.update.fail", code));
		}
		return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
	}

	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/createElectricFence", params = { "method=jimi.open.device.fence.create" }, produces = { "application/json" }, method = { RequestMethod.POST, RequestMethod.PUT })
	@Override
	public ResponseEntity<ResultModel> createElectricFence(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @Length(min = 15, max = 16, message = "api.imei.invalid") @RequestParam(value = "imei", required = true) String imei,
			@NotBlank(message = "api.fenceName.invalid") @Length(min = 1, max = 100, message = "api.fenceName.invalid") @RequestParam(value = "fence_name", required = true) String fenceName,
			@NotBlank(message = "api.alarmType.invalid") @MemberOf(value = { "in", "out", "in,out" }, message = "api.alarmType.invalid") @RequestParam(value = "alarm_type", required = true) String alarmType,
			@NotBlank(message = "api.reportMode.invalid") @MemberOf(value = { "0", "1" }, message = "api.alarmType.invalid") @RequestParam(value = "report_mode", required = true) String reportMode,
			@NotBlank(message = "api.alarmSwitch.invalid") @MemberOf(value = { "ON", "OFF" }, message = "api.alarmSwitch.invalid") @RequestParam(value = "alarm_switch", required = true) String alarmSwitch,
			@NotBlank(message = "api.lng.invalid") @RequestParam(value = "lng", required = true) String lng,
			@NotBlank(message = "api.lat.invalid") @RequestParam(value = "lat", required = true) String lat,
			@NotBlank(message = "api.radius.invalid") @Min(value = 1, message = "api.radius.invalid") @Max(value = 9999, message = "api.radius.invalid") @RequestParam(value = "radius", required = true) String radius,
			@NotBlank(message = "api.zoomLevel.invalid") @Min(value = 3, message = "api.zoomLevel.invalid") @Max(value = 19, message = "api.zoomLevel.invalid") @RequestParam(value = "zoom_level", required = true) String zoomLevel,
			@NotBlank(message = "api.mapType.invalid") @MemberOf(value = { "BAIDU", "GOOGLE" }, message = "api.mapType.invalid") @RequestParam(value = "map_type",  defaultValue = "", required = true) String mapType,
			HttpServletRequest request) {
		String decrypt = DESEncrypt.decrypt(appKey);
		String[] strs = decrypt.split(",");
		String projectCode = strs[0];
		String userId = strs[1];
		DeviceInfoOutputDto deviceInfoOutputDto = devicesApiService.checkDeviceRange(userId, imei);
		if(null == deviceInfoOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_DEVICE_ERROR), HttpStatus.OK);
		}
		ElectricFenceInputDto electricFenceInputDto = new ElectricFenceInputDto();
		electricFenceInputDto.setImei(imei);
		electricFenceInputDto.setFenceName(fenceName);
		electricFenceInputDto.setAlarmType(alarmType);
		electricFenceInputDto.setReportMode(reportMode);
		electricFenceInputDto.setAlarmSwitch(alarmSwitch);
		electricFenceInputDto.setLng(lng);
		electricFenceInputDto.setLat(lat);
		electricFenceInputDto.setRadius(radius);
		electricFenceInputDto.setZoomLevel(zoomLevel);
		electricFenceInputDto.setMcType(deviceInfoOutputDto.getMcType());
		ApiResult apiResult = devicesApiService.createElectricFence(electricFenceInputDto);
		String code = String.valueOf(apiResult.getResultCode());
		ResultModel resultModel = new ResultModel();
		if ("0".equals(code)) {
			resultModel.setCode(0);
			resultModel.setMessage(MessageSourceUtil.getMessage("api.fence.create.ok"));
		} else {
			resultModel.setCode(12003); // 创建电子围栏操作失败
			resultModel.setMessage(MessageSourceUtil.getMessage("api.fence.create.fail", code));
		}
		resultModel.setResult(apiResult.getResult());
		return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
	}
	
	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/deleteElectricFence", params = { "method=jimi.open.device.fence.delete" }, produces = { "application/json" }, method = { RequestMethod.POST, RequestMethod.DELETE })
	@Override
	public ResponseEntity<ResultModel> deleteElectricFence(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @Length(min = 15, max = 16, message = "api.imei.invalid") @RequestParam(value = "imei", required = true) String imei,
			@NotBlank(message = "api.instructNo.invalid") @RequestParam(value = "instruct_no", required = true) String instructNo,
			HttpServletRequest request) {
		String decrypt = DESEncrypt.decrypt(appKey);
		String[] strs = decrypt.split(",");
		String projectCode = strs[0];
		String userId = strs[1];
		DeviceInfoOutputDto deviceInfoOutputDto = devicesApiService.checkDeviceRange(userId, imei);
		if(null == deviceInfoOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_DEVICE_ERROR), HttpStatus.OK);
		}
		ApiResult apiResult = devicesApiService.deleteElectricFence(imei, deviceInfoOutputDto.getMcType(), instructNo);
		String code = String.valueOf(apiResult.getResultCode());
		ResultModel resultModel = new ResultModel();
		if ("0".equals(code)) {
			resultModel.setCode(0);
			resultModel.setMessage(MessageSourceUtil.getMessage("api.fence.delete.ok"));
		} else {
			resultModel.setCode(12004); // 删除电子围栏操作失败
			resultModel.setMessage(MessageSourceUtil.getMessage("api.fence.delete.fail", code));
		}
		resultModel.setResult(apiResult.getResult());
		return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
	}
	
	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/getDeviceLocationMap", params = { "method=jimi.open.device.location.map" }, produces = { "application/json" }, method = { RequestMethod.GET, RequestMethod.POST })
	@Override
	public ResponseEntity<ResultModel> getDeviceLocationMap(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.imei.invalid") @Length(min = 15, max = 16, message = "api.imei.invalid") @RequestParam(value = "imei", required = true) String imei,
			@RequestParam(value = "map_type",  defaultValue = "", required = false) String mapType, HttpServletRequest request) {
		if(StringUtils.isNotBlank(mapType) && (!"BAIDU".equals(mapType) && !"GOOGLE".equals(mapType))) {
			return new ResponseEntity<ResultModel>(new ResultModel(ApiErrorCode.PARAM_MAPTYPE_ERROR), HttpStatus.OK);
		}
		String decrypt = DESEncrypt.decrypt(appKey);
		String[] strs = decrypt.split(",");
		String projectCode = strs[0];
		String userId = strs[1];
		DeviceInfoOutputDto deviceInfoOutputDto = devicesApiService.checkDeviceRange(userId, imei);
		if(null == deviceInfoOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_DEVICE_ERROR), HttpStatus.OK);
		}
		List<DeviceLocationInfoOutputDto> deviceLocationInfo = devicesApiService.getLocations(imei, mapType);
		if(null != deviceLocationInfo && deviceLocationInfo.size() > 0) {
			DeviceLocationInfoOutputDto deviceLocationInfoOutputDto = deviceLocationInfo.get(0);
			Map<String, Object> map = new HashMap<>();
			map.put("data", deviceLocationInfoOutputDto);
			String htmlDom = FreeMarkerUtil.getContent("deviceMap.ftl", map);
			ResultModel resultModel = new ResultModel();
			resultModel.setResult(htmlDom);
			return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
		}
		return new ResponseEntity<ResultModel>(new ResultModel(), HttpStatus.OK);
	}

	@ResponseBody
	@LoginSecurity
	@RequestMapping(value = "/moveDevice", params = { "method=jimi.open.device.move" }, produces = { "application/json" }, method = { RequestMethod.GET, RequestMethod.POST })
	@Override
	public ResponseEntity<ResultModel> moveDevice(
//			@NotBlank(message = "api.method.invalid") @Length(min = 10, max = 20, message = "api.method.invalid") @RequestParam(value = "method", required = true) String method,
			@NotBlank(message = "api.appkey.invalid") @Length(min = 10, max = 32, message = "api.appkey.invalid") @RequestParam(value = "app_key", required = true) String appKey,
//			@NotBlank(message = "api.timestamp.invalid") @DateRange(format = "yyyy-MM-dd HH:mm:ss", message = "api.timestamp.invalid") @RequestParam(value = "timestamp", required = true) String timestamp,
//			@NotBlank(message = "api.format.invalid") @MemberOf(value = { "json", "xml" }, message = "api.format.invalid") @RequestParam(value = "format", required = true) String format,
//			@NotBlank(message = "api.version.invalid") @MemberOf(value = { "1.0" }, message = "api.version.invalid") @RequestParam(value = "v", required = true) String v,
//			@NotBlank(message = "api.signmethod.invalid") @MemberOf(value = { "md5" }, message = "api.signmethod.invalid") @RequestParam(value = "sign_method", required = true) String signMethod,
//			@NotBlank(message = "api.sign.invalid") @Length(min = 10, max = 32, message = "api.sign.invalid") @RequestParam(value = "sign", required = true) String sign,
			@NotBlank(message = "api.accessToken.invalid") @Length(min = 10, max = 32, message = "api.accessToken.invalid") @RequestParam(value = "access_token", required = true) String accessToken,
			@NotBlank(message = "api.userId.invalid") @Length(min = 3, max = 32, message = "api.userId.invalid") @RequestParam(value = "src_account", required = true) String srcAccount,
			@NotBlank(message = "api.imei.invalid") @RequestParam(value = "imeis", required = true) String imeis,
			@NotBlank(message = "api.userId.invalid") @Length(min = 3, max = 32, message = "api.userId.invalid") @RequestParam(value = "dest_account", required = true) String destAccount,
			HttpServletRequest request) {
		if (srcAccount.equals(destAccount)) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.PARAM_ERROR), HttpStatus.OK);
		}
		String[] imeisArray = imeis.split(",");
		if (imeisArray.length > 500) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.PARAM_ERROR), HttpStatus.OK);
		}
		String decrypt = DESEncrypt.decrypt(appKey);
		String[] strs = decrypt.split(",");
		String projectCode = strs[0];
		String userId = strs[1];
		CoreUserOutputDto srcUserOutputDto = userApiService.checkUserRange(userId, srcAccount);
		if (null == srcUserOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_USER_ERROR), HttpStatus.OK);
		}
		CoreUserOutputDto destUserOutputDto = userApiService.checkUserRange(userId, destAccount);
		if (null == destUserOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_USER_ERROR), HttpStatus.OK);
		}
		String srcUserId = String.valueOf(srcUserOutputDto.getId());
		String destUserId = String.valueOf(destUserOutputDto.getId());
		CoreUserOutputDto coreUserOutputDto = userApiService.checkUserRange(srcUserId, destAccount);
		if (null == coreUserOutputDto) {
			return new ResponseEntity<ResultModel>(new ResultModel(ErrorCode.INVALID_USER_ERROR), HttpStatus.OK);
		}
		String code = devicesApiService.moveDevice(srcUserId, destUserId, imeis);
		ResultModel resultModel = new ResultModel();
		if ("0".equals(code)) {
			resultModel.setCode(0);
			resultModel.setMessage(MessageSourceUtil.getMessage("api.device.move.ok"));
		} else {
			resultModel.setCode(12002); // 转移/销售设备操作失败
			resultModel.setMessage(MessageSourceUtil.getMessage("api.device.move.fail", code));
		}
		return new ResponseEntity<ResultModel>(resultModel, HttpStatus.OK);
	}
}
